import { SearchOutlined, LoadingOutlined, InfoCircleOutlined } from '@ant-design/icons'
import { useBoolean } from '@gnlab/utils/env-react'
import { Checkbox, Input, Select } from 'antd'
import type { OrderedSet } from 'immutable'
import uniq from 'lodash/uniq'
import AutoSizer from 'react-virtualized-auto-sizer'
import { FixedSizeList as List } from 'react-window'
import InfiniteLoader from 'react-window-infinite-loader'
import { Empty } from '@/desktop/components'
import ChooseExternalTagsModal from '@/desktop/components/ChooseExternalTags'
import  defaultAvatar  from '@/desktop/assets/avatar.jpg'
import type { ExternalContact, ExternalItemTag } from '@/services/contact-types'
import type { AccountQywx } from '@/services/qywxs'
import {
  type Cache,
  type ChoosingItem,
  useManualSearching,
  useManualItems,
  useManualChooseAll,
} from './logics'
import './manual.module.less'

export function ManualChoose(props: {
  cache: Cache
  configQywxs: AccountQywx[]
  choosed: OrderedSet<string> // 已选中联系人 id
  choose: (contact: ExternalContact[], isChoosed: boolean) => void
}) {
  const { cache, configQywxs, choosed, choose } = props

  const {
    keyword,
    setKeyword,
    tags,
    setTags,
    wxid,
    setWxid,
    searchedContacts,
    searchLoaderProps,
    searching,
  } = useManualSearching(configQywxs)
  const { status, showingItems } = useManualItems(searchedContacts, choosed, cache)
  const { allChoosed, chooseAll } = useManualChooseAll(showingItems, choose)

  // 此函数每次重新生成，会导致列表里的元素都重新“生成“（不是重新渲染，是重新生成组件并挂载），因此尽量不要有依赖
  const Item = useCallback(
    ({
      data,
      index,
      style,
    }: {
      data: ChoosingItem[]
      index: number
      style: React.CSSProperties
    }) => {
      const { choosed, contact, qywx } = data[index]!
      return <div style={style} styleName="contact-row" onClick={() => choose([contact], !choosed)}>
        <div styleName="choose">
          <Checkbox checked={choosed}></Checkbox>
        </div>
        <div styleName="contact">
          <img loading="lazy" src={contact.avatar || defaultAvatar} />
          <div styleName="name">{contact.name}</div>
        </div>
        <div styleName="qywx">{qywx.friendlyFullName}</div>
      </div>
    },
    [choose],
  )
  const itemKey = useCallback((index: number, list: ChoosingItem[]) => list[index]!.contact.id, [])

  function renderContacts() {
    if (status === 'no-conditions')
      return <div styleName="no-conditions">
        <InfoCircleOutlined />
        <span>请指定搜索条件</span>
      </div>
    if (status === 'empty') return <Empty styleName="empty" description="没有匹配的联系人" />

    return <AutoSizer>
      {({ width, height }) => <InfiniteLoader {...searchLoaderProps}>
        {({ onItemsRendered, ref }) => <List
          ref={ref}
          onItemsRendered={onItemsRendered}
          height={height}
          width={width}
          itemCount={showingItems.length}
          itemSize={70}
          itemData={showingItems}
          itemKey={itemKey}
        >
          {Item}
        </List>}
      </InfiniteLoader>}
    </AutoSizer>
  }

  return <div styleName="manual-choose">
    <header>
      <Input
        prefix={<SearchOutlined />}
        placeholder="搜索客户"
        allowClear
        value={keyword}
        onChange={e => setKeyword(e.target.value)}
      />
      <div styleName="filter-row">
        <div styleName="filter-item">
          <label>标签：</label>
          <ChooseTags qywxs={configQywxs} choosed={tags} onChoosed={setTags} />
        </div>
        <div styleName="filter-item">
          <label>企业微信：</label>
          <Select
            allowClear
            placeholder="选择企业微信"
            options={configQywxs.map(qywx => ({
              label: qywx.friendlyFullName,
              value: qywx.wxid,
            }))}
            value={wxid}
            onChange={setWxid}
          />
        </div>
      </div>
    </header>

    <main>
      {searching ? (
        <div styleName="loading">
          <LoadingOutlined />
          加载中...
        </div>
      ) : null}
      <div styleName="contacts-header">
        <div styleName="choose">
          <Checkbox
            disabled={allChoosed === null}
            checked={allChoosed === 2}
            indeterminate={allChoosed === 1}
            onClick={chooseAll}
          />
        </div>
        <div styleName="contact">客户</div>
        <div styleName="qywx">所属企微</div>
      </div>
      <div styleName="contacts-wrapper">{renderContacts()}</div>
    </main>
  </div>
}

function ChooseTags(props: {
  qywxs: AccountQywx[]
  choosed: ExternalItemTag[]
  onChoosed: (choosed: ExternalItemTag[]) => void
}) {
  const { qywxs, choosed, onChoosed } = props
  const [choosing, startChoose, finishChoose] = useBoolean(false)
  const corpIds = useMemo(() => uniq(qywxs.map(qywx => qywx.corpid)), [qywxs])

  const selectOptions = choosed.map(item => ({ label: item.name, value: item.id }))
  const selectValue = choosed.map(item => item.id)

  return <>
    <Select
      mode="multiple"
      open={false}
      onDropdownVisibleChange={startChoose}
      allowClear
      value={selectValue}
      options={selectOptions}
      onChange={ids => onChoosed(ids.map(id => choosed.find(v => v.id === id)!))}
    />

    <ChooseExternalTagsModal
      visible={choosing}
      title="按标签搜索客户"
      corpIds={corpIds}
      choosed={choosed.map(t => t.id)}
      onFinish={tags => {
        if (tags) onChoosed(tags)
        finishChoose()
      }}
    />
  </>
}
